const fs = require('fs');
const path = require('path');
// ast
const parser = require('@babel/parser');

// 节点遍历
const traverse = require('@babel/traverse').default;

// es6 - 5
const babel = require('@babel/core');

// 分析依赖
function getModuleInfo(file) {
    const body = fs.readFileSync(file, 'utf-8');
    const ast = parser.parse(body, { sourceType: 'module' });

    // 依赖收集 import xxx
    const deps = {};
    traverse(ast, {
        ImportDeclaration({ node }) {
            const dirname = path.dirname(file);
            const abspath = './' + path.join(dirname, node.source.value);
            deps[node.source.value] = abspath;
        }
    })

    const { code } = babel.transformFromAst(ast, null, {
        presets: ['@babel/preset-env']
    });
    const info = {
        file, deps, code
    }
    return info;
}

const info = getModuleInfo('./src/index.js');
console.log('info', info);

/* 解析模块 */
function parseModules(file) {
    const entry = getModuleInfo(file);
    const temp = [entry];
    const depsGraph = {};
    getDeps(temp, entry);
    temp.forEach(info => {
        depsGraph[info.file] = {
            deps: info.deps,
            code: info.code
        }
    })
    return depsGraph
}

/* 获取依赖 */
function getDeps(temp, { deps }) {
    Object.keys(deps).forEach(key => {
        const child = getModuleInfo(deps[key]);
        temp.push(child);
        console.log('temp', temp);
        getDeps(temp, child);
    })
};

// const moduls = parseModules('./src/index.js');
// console.log('parseModules', moduls);

function bundle(file) {
    const depsGraph = JSON.stringify(parseModules(file));
    console.log(depsGraph);
    const tpl = `(function (graph) {
            function require(file) {
                function absRequire(relPath) {
                    return require(graph[file].deps[relPath])
                }
                var exports = {};
                (function (require, exports, code) {
                    eval(code)
                })(absRequire, exports, graph[file].code)
                return exports;
            }
            require('${file}')
        })(${depsGraph})`;
    return tpl
}

const content = bundle('./src/index.js');

!fs.existsSync('./dist') && fs.mkdirSync('./dist');
fs.writeFileSync('./dist/bundle.js', content);

